<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
define('INSTALL_ROOT', dirname(__FILE__));
require_once 'model.php';

// 添加会话支持
session_start();

$action = $_GET['action'] ?? 'index';
$install = new InstallModel();
$step = 1;
$template = '';

// 添加调试输出

switch ($action) {
    case 'env-check':
        $step = 2;
        $systemInfo = $install->systemList();
        $dirPermission = $install->checkDirPermission();
        $template = 'template/env-check.php';
        break;
        
    case 'db-config':
        $step = 3;
        $template = 'template/db-config.php';
        break;
        
    case 'execute':
        $step = 4;
        $template = 'template/execute.php';
        break;
        
    case 'complete':
        $step = 5;
        $template = 'template/complete.php';
        break;
        
    case 'test-db':
        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
            $config = $_POST;
            $result = $install->testDatabase($config);
            header('Content-Type: application/json');
            echo json_encode($result);
            exit;
        }
        break;
        
    case 'execute-step':
        header('Content-Type: text/event-stream');
        header('Cache-Control: no-cache');
        header('X-Accel-Buffering: no');

        if (ob_get_level()) ob_end_clean();
        
        try {
            $dbConfig = isset($_GET['config']) ? json_decode(urldecode($_GET['config']), true) : null;
            
            if (!$dbConfig) {
                throw new Exception('未找到数据库配置信息');
            }

            // 定义命令队列
            $commands = [
                [
                    'name' => '准备安装环境',
                    'type' => 'output',
                    'action' => function() {
                        sendMessage('output', '正在准备安装环境...');
                        return true;
                    }
                ],
                [
                    'name' => '验证数据库连接',
                    'type' => 'database',
                    'action' => function() use ($install, $dbConfig) {
                        sendMessage('detail', '正在验证数据库连接...');
                        $result = $install->testDatabase($dbConfig);
                        if(!$result['status']){
                            throw new Exception('数据库连接失败：' . $result['message']);
                        }
                        sendMessage('success', '数据库连接成功');
                        return true;
                    }
                ],
                [
                    'name' => '检查数据库状态',
                    'type' => 'database',
                    'action' => function() use ($install, $dbConfig) {
                        sendMessage('detail', '正在验证数据库是否为空...');
                        $result = $install->checkDatabaseEmpty($dbConfig);
                        if($result){
                            sendMessage('success', '数据库不为空');
                            $clearResult = $install->clearDatabase($dbConfig);
                            if(!$clearResult['status']){
                                throw new Exception('清空数据库失败：' . $clearResult['message']);
                            }
                            sendMessage('success', '数据库清空成功');
                        }else{
                            sendMessage('success', '数据库为空，可直接安装');
                        }
                        return true;
                    }
                ],
                [
                    'name' => '写入配置文件',
                    'type' => 'file',
                    'action' => function() use ($dbConfig) {
                        $envPath = __DIR__ . '/../../.env';
                        sendMessage('output', '检查配置文件...');
                        
                        $envContent = <<<EOT
APP_DEBUG = true

DB_TYPE = mysql
DB_HOST = {$dbConfig['db_host']}
DB_NAME = {$dbConfig['db_name']}
DB_USER = {$dbConfig['db_user']}
DB_PASS = {$dbConfig['db_password']}
DB_PORT = {$dbConfig['db_port']}
DB_CHARSET = utf8
DB_PREFIX   = {$dbConfig['db_prefix']}

DEFAULT_LANG = zh-cn
EOT;

                        sendMessage('output', '正在写入配置文件...');
                        if (file_put_contents($envPath, $envContent) === false) {
                            throw new Exception('写入配置文件失败');
                        }
                        sendMessage('success', '配置文件写入成功');
                        return true;
                    }
                ],
                [
                    'name' => '检查并安装依赖',
                    'type' => 'composer',
                    'action' => function() use ($install) {
                        sendMessage('output', '开始检查 Composer 依赖...');
                        
                        // 获取项目根目录
                        $rootPath = dirname(dirname(__DIR__));
                        
                        // 检查 vendor 目录是否存在
                        if (is_dir($rootPath . '/vendor') && file_exists($rootPath . '/vendor/autoload.php')) {
                            sendMessage('detail', '检测到已安装依赖');
                            
                            // 检查 composer.lock 文件
                            if (file_exists($rootPath . '/composer.lock')) {
                                sendMessage('detail', '验证依赖完整性...');
                                
                                // 执行 composer validate
                                $validateCommand = 'composer validate';
                                $process = proc_open($validateCommand, [
                                    0 => ["pipe", "r"],
                                    1 => ["pipe", "w"],
                                    2 => ["pipe", "w"]
                                ], $pipes, $rootPath);
                                
                                if (is_resource($process)) {
                                    fclose($pipes[0]);
                                    $output = stream_get_contents($pipes[1]);
                                    $error = stream_get_contents($pipes[2]);
                                    fclose($pipes[1]);
                                    fclose($pipes[2]);
                                    $return_value = proc_close($process);
                                    
                                    if ($return_value === 0) {
                                        sendMessage('success', '依赖完整性验证通过');
                                        return true;
                                    }
                                }
                            }
                        }
                        
                        sendMessage('detail', '正在安装依赖...');
                        
                        // 设置描述符
                        $descriptorspec = array(
                            0 => array("pipe", "r"),
                            1 => array("pipe", "w"),
                            2 => array("pipe", "w")
                        );
                        
                        // 构建安装命令
                        $command = 'composer install --no-interaction';
                        
                        // 打开进程
                        $process = proc_open($command, $descriptorspec, $pipes, $rootPath);
                        
                        if (is_resource($process)) {
                            // 关闭标准输入
                            fclose($pipes[0]);
                            
                            // 设置非阻塞模式
                            stream_set_blocking($pipes[1], 0);
                            stream_set_blocking($pipes[2], 0);
                            
                            // 持续读取输出直到进程结束
                            while (true) {
                                $status = proc_get_status($process);
                                
                                // 读取标准输出
                                $stdout = stream_get_contents($pipes[1]);
                                if ($stdout) {
                                    sendMessage('detail', trim($stdout));
                                }
                                
                                // 读取错误输出
                                $stderr = stream_get_contents($pipes[2]);
                                if ($stderr) {
                                    sendMessage('error', trim($stderr));
                                }
                                
                                // 如果进程已结束，退出循环
                                if (!$status['running']) {
                                    break;
                                }
                                
                                usleep(100000);
                            }
                            
                            // 关闭管道
                            fclose($pipes[1]);
                            fclose($pipes[2]);
                            
                            // 获取进程退出码
                            $return_value = proc_close($process);
                            
                            if ($return_value === 0) {
                                sendMessage('success', 'Composer 依赖安装完成');
                                return true;
                            } else {
                                throw new Exception('Composer 依赖安装失败');
                            }
                        } else {
                            throw new Exception('无法启动 Composer 安装进程');
                        }
                    }
                ],
                [
                    'name' => '安装数据库',
                    'type' => 'database',
                    'action' => function() use ($install, $dbConfig) {
                        sendMessage('output', '开始执行数据库安装...');
                        
                        // 获取项目根目录
                        $rootPath = dirname(dirname(__DIR__));
                        
                        // 构建命令
                        $command = 'php think migrate:run --app=adminapi';
                        sendMessage('detail', '执行命令: ' . $command);
                        
                        // 设置描述符
                        $descriptorspec = array(
                            0 => array("pipe", "r"),  // stdin
                            1 => array("pipe", "w"),  // stdout
                            2 => array("pipe", "w")   // stderr
                        );
                        
                        // 设置工作目录和环境变量
                        $cwd = $rootPath;
                        $env = array('PATH' => getenv('PATH'));
                        
                        // 打开进程
                        $process = proc_open($command, $descriptorspec, $pipes, $cwd, $env);
                        
                        if (is_resource($process)) {
                            // 关闭标准输入
                            fclose($pipes[0]);
                            
                            // 设置非阻塞模式
                            stream_set_blocking($pipes[1], 0);
                            stream_set_blocking($pipes[2], 0);
                            
                            $output = '';
                            
                            // 持续读取输出直到进程结束
                            while (true) {
                                $status = proc_get_status($process);
                                
                                // 读取标准输出
                                $stdout = stream_get_contents($pipes[1]);
                                if ($stdout) {
                                    sendMessage('detail', trim($stdout));
                                    $output .= $stdout;
                                }
                                
                                // 读取错误输出
                                $stderr = stream_get_contents($pipes[2]);
                                if ($stderr) {
                                    sendMessage('error', trim($stderr));
                                    $output .= $stderr;
                                }
                                
                                // 如果进程已结束，退出循环
                                if (!$status['running']) {
                                    break;
                                }
                                
                                // 短暂休眠以避免CPU过度使用
                                usleep(100000);
                            }
                            
                            // 关闭管道
                            fclose($pipes[1]);
                            fclose($pipes[2]);
                            
                            // 获取进程退出码
                            $return_value = proc_close($process);
                            
                            // 检查执行结果
                            if ($return_value === 0 || strpos($output, 'All Done') !== false) {
                                sendMessage('success', '数据库迁移执行完成');
                                return true;
                            } else {
                                if (empty($output)) {
                                    sendMessage('error', '命令没有产生任何输出');
                                }
                                throw new Exception('命令执行失败，退出码：' . $return_value);
                            }
                        } else {
                            throw new Exception('无法启动进程');
                        }
                    }
                ],
                // [
                //     'name' => '前端环境安装',
                //     'type' => 'frontend',
                //     'action' => function() {
                //         sendMessage('output', '开始检查前端环境...');
                        
                //         // 获取项目根目录和前端目录
                //         $rootPath = dirname(dirname(__DIR__));
                //         $frontendPath = $rootPath . '/template/adminapi';
                        
                //         try {
                //             // 检查前端目录是否存在
                //             if (!is_dir($frontendPath)) {
                //                 throw new Exception('前端目录不存在：' . $frontendPath);
                //             }
                            
                //             // 检查 Node.js 是否安装
                //             sendMessage('detail', '检查 Node.js 环境...');
                //             $nodeVersion = trim(shell_exec('node -v'));
                //             if (empty($nodeVersion)) {
                //                 throw new Exception('未检测到 Node.js，请先安装 Node.js');
                //             }
                //             sendMessage('success', 'Node.js 版本: ' . $nodeVersion);
                            
                //             // 检查 Yarn 是否安装
                //             sendMessage('detail', '检查 Yarn 环境...');
                //             $yarnVersion = trim(shell_exec('yarn -v'));
                //             if (empty($yarnVersion)) {
                //                 throw new Exception('未检测到 Yarn，请先安装 Yarn');
                //             }
                //             sendMessage('success', 'Yarn 版本: ' . $yarnVersion);
                            
                //             // 检查是否已经安装过依赖
                //             if (is_dir($frontendPath . '/node_modules') && file_exists($frontendPath . '/yarn.lock')) {
                //                 sendMessage('detail', '检测到已存在的依赖...');
                //             } else {
                //                 // 执行 yarn install
                //                 sendMessage('detail', '开始安装前端依赖...');
                //                 $descriptorspec = [
                //                     0 => ["pipe", "r"],
                //                     1 => ["pipe", "w"],
                //                     2 => ["pipe", "w"]
                //                 ];
                                
                //                 // 在前端目录中执行命令
                //                 $process = proc_open('yarn install', $descriptorspec, $pipes, $frontendPath);
                                
                //                 if (is_resource($process)) {
                //                     // 设置非阻塞模式
                //                     stream_set_blocking($pipes[1], 0);
                //                     stream_set_blocking($pipes[2], 0);
                                    
                //                     // 持续读取输出直到进程结束
                //                     while (true) {
                //                         $status = proc_get_status($process);
                                        
                //                         // 读取标准输出
                //                         $stdout = stream_get_contents($pipes[1]);
                //                         if ($stdout) {
                //                             sendMessage('detail', trim($stdout));
                //                         }
                                        
                //                         // 读取错误输出
                //                         $stderr = stream_get_contents($pipes[2]);
                //                         if ($stderr) {
                //                             sendMessage('error', trim($stderr));
                //                         }
                                        
                //                         // 如果进程已结束，退出循环
                //                         if (!$status['running']) {
                //                             break;
                //                         }
                                        
                //                         usleep(100000);
                //                     }
                                    
                //                     // 关闭管道
                //                     fclose($pipes[0]);
                //                     fclose($pipes[1]);
                //                     fclose($pipes[2]);
                                    
                //                     $return_value = proc_close($process);
                //                     if ($return_value !== 0) {
                //                         throw new Exception('前端依赖安装失败');
                //                     }
                                    
                //                     sendMessage('success', '前端依赖安装完成');
                //                 }
                //             }
                            
                //             // 执行 yarn build
                //             sendMessage('detail', '开始构建前端资源...');
                //             $process = proc_open('yarn build', $descriptorspec, $pipes, $frontendPath);
                            
                //             if (is_resource($process)) {
                //                 // 设置非阻塞模式
                //                 stream_set_blocking($pipes[1], 0);
                //                 stream_set_blocking($pipes[2], 0);
                                
                //                 // 持续读取输出直到进程结束
                //                 while (true) {
                //                     $status = proc_get_status($process);
                                    
                //                     // 读取标准输出
                //                     $stdout = stream_get_contents($pipes[1]);
                //                     if ($stdout) {
                //                         sendMessage('detail', trim($stdout));
                //                     }
                                    
                //                     // 读取错误输出
                //                     $stderr = stream_get_contents($pipes[2]);
                //                     if ($stderr) {
                //                         sendMessage('error', trim($stderr));
                //                     }
                                    
                //                     // 如果进程已结束，退出循环
                //                     if (!$status['running']) {
                //                         break;
                //                     }
                                    
                //                     usleep(100000);
                //                 }
                                
                //                 // 关闭管道
                //                 fclose($pipes[0]);
                //                 fclose($pipes[1]);
                //                 fclose($pipes[2]);
                                
                //                 $return_value = proc_close($process);
                //                 if ($return_value !== 0) {
                //                     throw new Exception('前端资源构建失败');
                //                 }
                                
                //                 sendMessage('success', '前端资源构建完成');
                //             }
                            
                //             return true;
                            
                //         } catch (Exception $e) {
                //             sendMessage('error', '前端环境配置失败: ' . $e->getMessage());
                //             throw $e;
                //         }
                //     }
                // ],
                // [
                //     'name' => 'Node',
                // ]
                [
                    "name" => "最后初始化",
                    "type" => "output",
                    "action" => function() use ($install) {
                        sendMessage('output', '开始初始化...');
                        
                        // 获取 public 目录路径
                        $publicPath = dirname(dirname(__DIR__)) . '/public';
                        $lockFile = $publicPath . '/install.lock';
                        
                        try {
                            // 创建锁文件
                            $content = date('Y-m-d H:i:s');
                            if (file_put_contents($lockFile, $content) === false) {
                                throw new Exception('无法创建安装锁定文件');
                            }
                            
                            // 验证文件是否创建成功
                            if (!file_exists($lockFile)) {
                                throw new Exception('安装锁定文件创建失败');
                            }
                            
                            sendMessage('success', '安装锁定文件创建成功');
                            return true;
                            
                        } catch (Exception $e) {
                            sendMessage('error', '初始化失败: ' . $e->getMessage());
                            throw $e;
                        }
                    }
                ]
            ];

            // 执行命令队列
            $totalSteps = count($commands);
            foreach($commands as $index => $command) {
                try {
                    sendMessage('step', "执行步骤 " . ($index + 1) . "/{$totalSteps}: {$command['name']}", 
                        ($index + 1) * (100 / $totalSteps));
                    $command['action']();
                } catch (Exception $e) {
                    sendMessage('error', "执行 {$command['name']} 失败: " . $e->getMessage());
                    throw $e;
                }
            }

            sendMessage('complete', '安装完成！');

        } catch (Exception $e) {
            sendMessage('error', '安装失败：' . $e->getMessage());
        }

        sendMessage('close');
        exit;
        break;
        
    default:
        $step = 1;
        $template = 'template/index.php';
        break;
}


// 检查模板文件是否存在
if (!file_exists($template)) {
    die('模板文件不存在：' . $template);
}

// 加载主模板
include 'template/main.php';

// 添加一个辅助函数来发送消息
function sendMessage($type, $content = '', $progress = 0) {
    echo "data: " . json_encode([
        'type' => $type,
        'content' => $content,
        'progress' => $progress
    ]) . "\n\n";
    ob_flush();
    flush();
    usleep(100000); // 添加小延迟使输出更平滑
}